perm filename SCENE.SAI[SYS,HE] blob sn#103136 filedate 1974-06-07 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00010 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	SCENE - cross-reference  mapping schemes
C00005 00003	_ LCOMCV, MERGE
C00007 00004	_	Debugging output routines for fail code
C00014 00005	_ XREF
C00016 00006	_	XREF cont
C00019 00007	_	XREF cont
C00022 00008	_	XREF cont.
C00025 00009	_	XREF cont
C00038 00010	_ UNXREF
C00040 ENDMK
C⊗;
COMMENT SCENE - cross-reference  mapping schemes;

ENTRY LCOMCV,XREF,UNXREF;

BEGIN "SCENE"
REQUIRE "⊂⊃||" DELIMITERS;

DEFINE QI=⊂INTEGER⊃,
	QR=⊂REAL⊃,
	QRI=⊂REFERENCE INTEGER⊃,
	QRR=⊂REFERENCE REAL⊃,
	QEP=⊂EXTERNAL SIMPLE PROCEDURE⊃,
	QEIP=⊂EXTERNAL SIMPLE INTEGER PROCEDURE⊃,
	QERP=⊂EXTERNAL SIMPLE REAL PROCEDURE⊃,
	QFOP=⊂FORWARD INTERNAL SIMPLE PROCEDURE⊃,
	QFOIP=⊂FORWARD INTERNAL SIMPLE INTEGER PROCEDURE⊃,
	QFORP=⊂FORWARD INTERNAL SIMPLE REAL PROCEDURE⊃,
	_=⊂COMMENT⊃,
	LOOP(I,J,K,L)=⊂FOR I←J STEP L UNTIL K DO⊃,
	BELCRE(IA)=⊂LVNEXT(IA,-1)⊃,
	SAFEX=⊂SAFE⊃,
	TAB=⊂"	"⊃,
	TAB1=⊂TAB&TAB⊃,
	CRLF=⊂'15&'12⊃,
	INT(A,S)=⊂"  A="&CVS(S)⊃,
	FINT(A,S)=⊂"  A="&CVF(S)⊃,
	BINT(A,S)=⊂"  A="&(IF S THEN "YES" ELSE "NO")⊃,	
	WRITE(S)=⊂IF XTRACE THEN OUT(12,S&CRLF)⊃;

INTEGER IA,IB,IC,ID,IE,LNCS1,LNCS2;
EXTERNAL INTEGER IFREEV,MAXNOL,MAXNOV,LNCRE1,LNCRE2,XTRACE,IDUM,NLPT;
INTERNAL INTEGER I1,IV1,IV2,I2,IX1,IX2,IP1,IP2,IL,ICV1,ICV2,ISV1,ISV2;
INTERNAL REAL R1,R2,RX;
EXTERNAL REAL X, Y, RWIC,RMLE,RCDI,RMALS,RMRLS;
REAL RMLES,RMALSS,RMRLSS,RCDIS,RWICS;

SAFEX EXTERNAL INTEGER ARRAY LCREDE,LVERSI,LVERCO,LVER,IPK,IPS,LINK[1:1];

SAFEX EXTERNAL REAL ARRAY XVCOR,YVCOR,SVANG,XLCOR,YLCOR,RK,RBK,RAS,RBS,
	RCOL,RLEN[1:1];

QEIP ISIGN(QI I,J);
QEIP LVNEXT(QI I,J);
QEIP LVOPP(QI I);
QEIP MERCV(QI I,J,K);
QEIP NLINCV(QI I);
QERP LDIST(QR X,Y; QI I);
QEIP NEXVER;
QEP RETCV(INTEGER ICV);
QEIP LACT(QI I);
QEP ARINT(QRI IPK; QRR RBK,RK,RAS,RBS,RCOL; QRI IPS);
QEP XREF1(QR A,B; QRI LCV1; QR C,D,E,F);
_ LCOMCV, MERGE

_	Returns number of common line, or 0 if no such line.
	Counts all types and connections.;

INTERNAL SIMPLE INTEGER PROCEDURE LCOMCV(INTEGER ICV1,ICV2);
	BEGIN "LCOMCV"
	LABEL L1;
	INTEGER ISV, ISVM;
	ISV←ABS LVNEXT(ICV1,8);
L1:	IF ISV=0 THEN RETURN(0);
	ISVM ← (ISV+1)%2;
	IF LACT(ISVM)∧LVERCO[LVOPP(ISV)]=ICV2 THEN RETURN(ISVM);

_	No, this line is inactive or not common to ICV1 and ICV2, iterate.;

	ISV←ABS LVNEXT(0,8);
	GO L1;
	END "LCOMCV";

QEIP XREF21;
QEIP XREF22;
QEIP XREF30;
QEIP XREF31;
QEIP XREF32;
QEIP XREF41;
QEIP XREF42;
QEIP XREF50;
QEIP XREF52;
QEIP XREF51;
QEP XREF6;
QEIP XREF7;
QEP XREF8;
QEP INNER(QI B1,B2);
QEP CUTJN(BOOLEAN A);
QEP XJOIN(BOOLEAN A);

_	merge CV C1 and C2;

INTERNAL SIMPLE BOOLEAN PROCEDURE MERGE(INTEGER C1, C2, CODE);
	BEGIN
	INTEGER RESULT;
	RESULT ← MERCV(C1,C2,CODE);
	WRITE(|TAB1&"merge "&INT(CV 1,C1)&INT(CV 2,C2)&INT(FLAG,CODE)&
		INT(NEW CV,RESULT)|);
	RETURN(RESULT);
	END;
_	Debugging output routines for fail code;

INTERNAL SIMPLE PROCEDURE DINS(INTEGER V);
	WRITE(TAB1&"line "&CVS(V DIV 2)&" wholely inside line "&
		CVS(IF IDUM=-2 THEN ISV2 DIV 2 ELSE ISV1 DIV 2));

INTERNAL SIMPLE PROCEDURE DCOLIN(INTEGER SV1, SV2);
	WRITE(TAB1&"SV "&CVS(SV1)&" and SV "&CVS(SV2)&" are colinear");

INTERNAL SIMPLE PROCEDURE DEBOUT;
	OUT(12,TAB&INT(SV1,I1)&INT(SV2,I2)&INT(KARN,IDUM)&INT(X1,IP1)&
		INT(X2,IP2)&FINT(D1,R1)&FINT(D2,R2)&CRLF);

INTERNAL SIMPLE PROCEDURE DMINUM(INTEGER V1, V2);
	WRITE(TAB1&"minimum from SV "&CVS(V1)&" to SV "&CVS(ABS V2)&
		(IF V2<0 THEN " - collinear" ELSE NULL));

INTERNAL SIMPLE PROCEDURE DCROSS(INTEGER V1, V2);
	WRITE(TAB1&" vertex "&CVS(V1)&" intersets inside vertex "&CVS(V2));

INTERNAL SIMPLE PROCEDURE DTJOIN(INTEGER CV,SV);
	WRITE(|TAB1&" t-joint: SVs "&CVS(IV1)&" and "&CVS(IV2)&
		INT(SV,SV)&" of "&INT(CV,CV)&" shortened"|);

INTERNAL SIMPLE PROCEDURE DCLEAR(INTEGER SV);
	WRITE(TAB1&"Clear link from SV "&CVS(SV)&" to SV "&CVS(IPS[SV]));

INTERNAL SIMPLE PROCEDURE DCUTJN(INTEGER I2,I3,I4; REAL A1,A2; INTEGER LN);
	WRITE(|TAB&"cut join "&INT(SV1,I1)&INT(SV2,I2)&BINT(1¬BARE,I3)&
		BINT(2¬BARE,I4)&FINT(D1,A1)&FINT(D2,A2)&
		FINT(CD2,RK[I2])&FINT(LEN2,RLEN[LN])|);

INTERNAL SIMPLE PROCEDURE DJOIN1(INTEGER I3; REAL A1);
	WRITE(|TAB&"join "&INT(SV1,I1)&INT(SV2,I3)&FINT(CD1,A1)&
		FINT(D2,RBS[I1])&FINT(CD2,RK[I1])|);

INTERNAL SIMPLE PROCEDURE DJOIN2(INTEGER IS1,IS2);
	WRITE(|TAB1&BINT(1BARE,IS1)&BINT(2BARE,IS2)|);

INTERNAL SIMPLE PROCEDURE DJOIN3(REAL D; INTEGER B1);
		WRITE(|TAB&TAB1&FINT(DIST,D)&BINT(USE RCDIS,B1)|);
_ XREF;

_	Sets up cross-reference tables, based on line intersections,
	and uses those tables as a basis for the creation of temporary
	compound vertices. Those will later be utilized in the object
	abstraction schemes. Collinearities are also recorded as midway-point
	intersections. The program only works with active lines.;

INTERNAL SIMPLE PROCEDURE XREF;
	BEGIN "XREF" LABEL L200;
	INTEGER I3,LCV1,LCV2,PS,LB,IS1,IS2,M1,IS,JS;
	ARINT(IPK[1],RBK[1],RK[1],RAS[1],RBS[1],RCOL[1],IPS[1]);

_	First prepare the distance tables.;

	RX←RMLES←RMLE↑2;
	RMALSS←RMALS↑2;
	RMRLSS←RMRLS↑2;
	RCDIS←RCDI↑2;
	RWICS←RWIC↑2;
	XREF1(RCDIS,RWICS,LCV1,RMLES,RMALSS,RWIC,RMRLSS);
	ARRCLR(RK,900000.);
	ARRCLR(RAS,900000.);
	ARRCLR(RCOL,900000.);
	GETFORMAT(IS,JS);
	SETFORMAT(0,2);
	IF XTRACE THEN
		BEGIN
		OPEN(12,"DSK",0,0,2,I1,I1,I1);
		ENTER(12,"XTRC"&NLPT&".LPT",I1);
		OUTSTR("FILE IS "&NLPT&CRLF);
		NLPT ← NLPT+1;
		END;

_	The following is the MAIN  X-REF SETUP LOOP
	first iteration use RMLE;

	WRITE(|"PASS 0 - ITERATION 0"&FINT(TOLER,RX)|);
	M1 ← MAXNOL-1;
	LOOP(I1,1,M1,1) IF LACT(I1) THEN LOOP(I2,I1+1,MAXNOL,1)
	    IF XREF30 THEN INNER(R1≤RX∧R2≤RX,TRUE);
_	XREF cont;

_	second iteration - amend blocked intersections using RMLE;

	WRITE(|"PASS 0 - ITERATION 1"&FINT(TOLER,RX)|);
	LOOP(I1,1,MAXNOL,1) IF XREF21 THEN LOOP(I2,1,MAXNOL,1)
	    IF XREF31∧¬(IP1≤0∨IP2≤0∨(IP1=1∧¬ICV1)∨(IP1=2∧¬ICV2))∧
		XREF42 THEN INNER(R1≤RX∧R2≤RX,FALSE);

_	CROSS-REFERENCE TABLES NOW EXIST
	Now create temporary vertices and possible T-joints.
	pass 1:	Join acceptable extension-intersections, using RMLE↑2/4
	pass 2:	Same, except use RMLE↑2	;

	PS ← 0;
	FOR RX ← RMLES*.25,RMLES DO
		BEGIN "PASSC"
		PS ← PS+1;
		WRITE(|"PASS "&CVS(PS)&FINT(TOLER,RX)&FINT(RCDIS,RCDIS)&
			FINT(RWIC,RWIC)|);
		LOOP(I1,1,MAXNOV,1) IF XREF50 THEN XJOIN(PS=2);
		END "PASSC";

_	pass 3:	Join ends with small cut stops, iff either end is free,
		     giving preference to shortest RK of line-pair.
	pass 4: Same, except no preference.	;

	FOR PS ← 3,4 DO
		BEGIN "PASSD"
		WRITE(|"PASS "&CVS(PS)&FINT(TOLER,RX)&FINT(RMLES,RMLES)&
			FINT(RMALSS,RMALSS)&FINT(RMRLSS,RMRLSS)|);
		LOOP(I1,1,MAXNOV,1) IF XREF52 THEN CUTJN(PS=3);
		END "PASSD";

_	pass 5:	Join still free ends into closest vertices
		     provided distance and PLDIS are OK.	;

	RX ← RMLES*2;
	WRITE(|"PASS 5"&FINT(TOLER,RX)&FINT(RWICS,RWICS)|);
	LOOP(I1,1,MAXNOV,1) IF XREF51 THEN
		BEGIN "PASSE"
		R1←900000.;
		IP2←LVOPP(I1);
		XREF6;
		END "PASSE";
_	XREF cont;

_	pass 6:  Iterate extension intersections once more, using
			4*RMLE↑2 for sums and new XREF setup	;

	RX ← RMLES*4.;
	WRITE(|"PASS 6"&FINT(TOLER,RX)|);
	M1 ← MAXNOL-1;
	LOOP(I1,1,M1,1) IF XREF22 THEN LOOP(I2,I1+1,MAXNOL,1)
	    IF XREF32∧¬(IP1≤0∨IP2≤0)∧XREF41 THEN INNER((R1+R2)<RX,TRUE);
	LOOP(I1,1,MAXNOV,1) IF XREF51 THEN XJOIN(FALSE);

_	   *****   PRIMARY C.V. COMPOUNDS NOW EXIST   *****;

_	OK, by now all the intersection-indicated c.v:s are created.
	The next step is to merge neighbouring c.v:s, provided they
	are within the maximum distance, CDI, from one another, and
	that a line between them would not cross any other line in
	the topological picture.;

L200:	WRITE("START CV MERGE");
	M1 ← MAXNOV-1;

	LOOP(I1,1,M1,1)
		BEGIN "LP201" 

_		C.v. is active?;

		IF ¬BELCRE(I1) THEN CONTINUE;
		LOOP(I2,I1+1,MAXNOV,1)
			BEGIN "LP202" 

_			Second c.v. is active, as well?;

			IF ¬BELCRE(I2) THEN CONTINUE;

_			Yes, it	 is. Are they close enough?;

			IF XREF7 THEN CONTINUE;
			WRITE(|TAB&" active "&INT(CV 1,I1)&INT(CV 2,I2)&
				"      close enough"|);

_			Yes, they are. Do they have a line in common?;

			IF LCOMCV(I1,I2)≠0 THEN CONTINUE;
			WRITE(TAB1&"no common line");

_			No, they don't. Are they both single?;

			IF NLINCV(-I1)*NLINCV(-I2)=1 THEN CONTINUE;
			WRITE(TAB1&"not both single");
_	XREF cont.;

_			No, they aren't. Does their line-of-sight cross
			any line, in the TOPOLOGICAL picture? Check all
			active lines!;

		 	LOOP(I3,1,MAXNOV,2)
				BEGIN "LP203" 

_				Is the line active?;

				IF ¬LACT("(I3+1)%2") THEN CONTINUE;

_				Yes, it is. Find end c.v:s.;

				ICV1←LVERCO[I3];
				ICV2←LVERCO[I3+1];

_				Does the line belong to our two c.v:s?;

				IF (I1-ICV1)*(I1-ICV2)*(I2-ICV1)*
					(I2-ICV2)=0 THEN CONTINUE;

_				No, it doesn't. Check intersection.;

				XREF8;

_				If the lines cross, we lose. Try next
					second c.v.;

				IF IP1<0∧IP2<0 THEN
					BEGIN
					WRITE(|TAB1&" crossed by "&
					    INT(LINE,I3)|);
					CONTINUE "LP202";
					END;

_				The lines do not cross. Check the next one.;

		 	        END "LP203";

_			All lines are cleared. Merge I1 and I2.;

			IF MERGE(I1,I2,0) THEN GO L200;

_			After a merge, unfortunately, it is necessary to
			iterate all the way back (now or later), but on
			the other hand it won't happen very often!;

			END "LP202";
		END "LP201";
_	XREF cont;

_	Finally check collinearities. Negate links between all active,
	unjoined s.v:s where there are unjoined	crossing lines in between.
	Delete unreciprocated links.;

	WRITE("REDO COLLINEARITIES");
	LOOP(I1,1,MAXNOV,1)
		BEGIN "PASSX"
		INTEGER I3, I4, L1, L2, L3, L4;
		IL←(I1+1)%2;
		IF ¬LACT(IL) THEN CONTINUE;
		I2←ABS LINK[I1];
		IF ¬I2 THEN CONTINUE;
		IF ABS LINK[I2]≠I1 THEN
			BEGIN "PASSY"
			LINK[I1]←0;
			WRITE(|TAB&"delete link "&INT(SV 1,I1)&
				INT(SV 2,I2)|);
			CONTINUE;
			END "PASSY";
		L1 ← LVERCO[I1];
		L2 ← LVERCO[I2];
		IF L1=L2 THEN CONTINUE;
		I3 ← IPK[I1];
		I4 ← IPK[I2];
		IF I3 THEN L3 ← LVERCO[I3];
		IF I4 THEN L4 ← LVERCO[I4];
		R1 ← 4*RCOL[I1];
		IF I3∧RK[I1]<R1∧L1≠L3∨I4∧RK[I2]<R1∧L2≠L4 THEN
			BEGIN "PASSZ"
			LINK[I1]←-I2;
			LINK[I2]←-I1;
			WRITE(|TAB&"crossing line"&INT(SV 1,I1)&
				INT(SV 2,I2)|);
			END "PASSZ";
		END "PASSX";
	IF XTRACE THEN RELEASE(12);
	END "XREF";
_ UNXREF;

_	This procedure disconnects all active lines from each other.
	It assumes no inactive lines are connected to c.v.s containing
	active lines.;

INTERNAL SIMPLE PROCEDURE UNXREF;
	BEGIN "UNXREF"
	LOOP(IA,1,MAXNOL,1) IF LACT(IA) THEN
		BEGIN
		IB←2*IA;
		LOOP(IC,0,1,1)
			BEGIN
			LVER[ID←IB-IC]←ID;
			RETCV(LVERCO[ID]);
			SVANG[ID]←360.;
			END
		END;
	LOOP(IA,1,MAXNOL,1) IF LACT(IA) THEN
		BEGIN
		IB←2*IA;
		LOOP(IC,0,1,1)
			BEGIN
			IE ← NEXVER;
			ID←IB-IC;
			LVERSI[IE]←ID;
			LVERCO[ID]←IE;
			XVCOR[IE]←XLCOR[ID];
			YVCOR[IE]←YLCOR[ID]
			END
		END;
	END "UNXREF";

END "SCENE";